package woaini.wind.service.impl;
import java.sql.Timestamp;

import cn.hutool.core.util.StrUtil;
import io.minio.ObjectWriteResponse;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import woaini.wind.domain.MinIOConfig;
import woaini.wind.domain.MinIOContent;
import woaini.wind.exception.BadRequestException;
import woaini.wind.repository.MinIOConfigRepository;
import woaini.wind.repository.MinIOContentRepository;
import woaini.wind.service.IMinIOService;
import woaini.wind.service.dto.MinIOQueryCriteria;

import woaini.wind.utils.*;

import java.util.List;
import java.util.Optional;

/**
 * minI存储
 *
 * @see MinIOServiceImpl
 * @author yefeng {@date 2024-11-04 14:57:38}
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "minIO")
public class MinIOServiceImpl implements IMinIOService {

  private final MinIOContentRepository minIOContentRepository;
  private final MinIOConfigRepository minIOConfigRepository;

  @Value("${miniIO.max-size:15}")
  private Long maxSize;

  @PostConstruct
  public void init(){
    MinIOConfig minIOConfig = this.find();
    if (minIOConfig.getId() != null){
      try{
        MinIoUtil.initClient(minIOConfig);
      }catch (Exception e){
      }
    }
  }


  @Override
  @Cacheable(key = "'config'")
  public MinIOConfig find() {
    Optional<MinIOConfig> minIOConfig = minIOConfigRepository.findById(1L);
    return minIOConfig.orElseGet(MinIOConfig::new);
  }

  @Override
  public MinIOConfig config(MinIOConfig config) {
    config.setId(1L);
    String endpoint = config.getEndpoint();

    if (!(endpoint.startsWith("http://") || endpoint.startsWith("https://"))){
      throw new BadRequestException("Endpoint必须以http://或者https://开头");
    }
    MinIOConfig minIOConfig = minIOConfigRepository.save(config);
    //刷新配置
    MinIoUtil.initClient(minIOConfig);
    return minIOConfig;
  }

  @Override
  public PageResult<MinIOContent> queryAll(MinIOQueryCriteria criteria, Pageable pageable) {

    if (StrUtil.isNotEmpty(criteria.getKey())){
      return PageUtil.toPage(minIOContentRepository.findByKeyLike(criteria.getKey(),pageable));
    }else {
      return PageUtil.toPage(minIOContentRepository.findAll(pageable));
    }
  }

  @Override
  public List<MinIOContent> queryAll(MinIOQueryCriteria criteria) {
    return minIOContentRepository.findMinIOContentByKey(criteria.getKey());
  }

  @Override
  public MinIOContent upload(MultipartFile file, MinIOConfig config) {
    //校验
    FileUtil.checkSize(maxSize, file.getSize());
    MinIoUtil.getMinioClient();
    //开始上传

    String key = file.getOriginalFilename();
    String contentType = file.getContentType();

    try {
      ObjectWriteResponse writeResponse = MinIoUtil.uploadFile(config.getBucketName(), file, key, contentType);
      ValidationUtil.isActualTrue(writeResponse == null, "文件上传失败");
      //成功保存信息

      MinIOContent minIOContent = new MinIOContent();
      minIOContent.setKey(key);
      minIOContent.setBucket(writeResponse.bucket());
      minIOContent.setSize(String.valueOf(file.getSize()));
      minIOContent.setUrl(writeResponse.object());
      minIOContent.setSuffix(FileUtil.getSuffix(writeResponse.object()));
      minIOContent.setUpdateTime(new Timestamp(new java.util.Date().getTime()));
      return minIOContentRepository.save(minIOContent);
    } catch (Exception e) {
      throw new BadRequestException("文件上传失败");
    }
  }

  @Override
  public MinIOContent findByContentId(Long id) {

    Optional<MinIOContent> minIOContent = minIOContentRepository.findById(id);
    ValidationUtil.isActualTrue(minIOContent.isEmpty(),"文件不存在!");
    return minIOContent.get();
  }

  @Override
  public String download(MinIOContent content, MinIOConfig config) {
    return config.getEndpoint() + config.getSeparator() + config.getBucketName() + config.getSeparator() + content.getUrl();
  }

  @Override
  public void delete(MinIOContent content, MinIOConfig config) {

    String key = content.getKey();
    String bucketName = config.getBucketName();
    try {
      MinIoUtil.removeFile(bucketName,key);
      minIOContentRepository.delete(content);
    } catch (Exception e) {
      throw new BadRequestException(STR."文件删除失败:\{bucketName}/\{key}");
    }
  }

  @Override
  public void synchronize(MinIOConfig config) {}

  @Override
  public void deleteAll(Long[] ids, MinIOConfig config) {

    for (Long id : ids) {
      MinIOContent content = findByContentId(id);
      delete(content,config);
    }
  }
}
